<template>
  <vxe-pulldown v-model="visible">
    <template #default>
      <el-input
          type="text"
          v-model="selectValue"
          placeholder="请选择"
          readonly
          @focus="focusEvent"
          @mouseover="onMouseEvent.over"
          @mouseleave="onMouseEvent.level">
        <template #suffix>
          <el-icon v-if="showClear"
                   @mouseover="onMouseEvent.cleanOver"
                   @mouseleave="onMouseEvent.cleanLevel">
            <CircleCloseFilled v-if="cleanOver"
                               @click.stop="clearClick"/>
            <CircleClose v-else @click.stop="clearClick"/>
          </el-icon>
          <el-icon v-else>
            <caret-top v-if="visible"/>
            <caret-bottom v-else/>
          </el-icon>
        </template>
      </el-input>
    </template>
    <template #dropdown>
      <div :class="ns.be('option','input')" disabled>
        <el-input
            type="text"
            v-if="isSearch"
            v-model="searchInput"
            prefix-icon="search"
            @input="search"
            @clear="search"
            placeholder="输入关键词进行过滤"
            clearable/>
      </div>
      <div :class="ns.b('content')" :style="{paddingTop:isSearch?'40px':'0'}" disabled>
        <el-tree
            ref="treeRef"
            :="$attrs"
            :props="localProps"
            :data="treeData"
            @node-click="handleNodeClick"
            :filter-node-method="filterNode"
        ></el-tree>
      </div>
    </template>
  </vxe-pulldown>
</template>

<script setup>

import {nextTick, onMounted, reactive, ref, unref, useAttrs} from "vue";
import {ElMessage, useNamespace} from "element-plus";
import {getDistData} from "@/api/api-dist";

let ns = useNamespace("select-tree", ref('rk'));
//获取属性
const attrs = useAttrs()
//定义事件
const emits = defineEmits(['nodeClick'])
const visible = ref(false)
const props = defineProps({

  options: {
    type: Array,
  },
  /**
   * 字典项根据字典值查询，Object:{name:'XM_OBJ_NAME',params:{},dataLabel:'data'}
   */
  dist: {
    type: [String, Object],
    default: ""
  },
  /**
   * 节点点击时候关闭弹窗
   */
  nodeClickClose: {
    type: Boolean,
    default: false
  },
  /**
   * 存在code节点就展示Code数据
   */
  showCode: {
    type: Boolean,
    default: true
  },
  /**
   * 父节点是否支持选中
   */
  parentNodeClick: {
    type: Boolean,
    default: false
  },
  server: {
    type: Function,
  },
  isSearch: {
    type: Boolean,
    default: true
  },
  props: {
    type: Object,
    default: () => ({
      children: "children",
      label: "label",
      disabled: "disabled"
    })
  },
})

const localProps = reactive(props.props)

const showClear = ref(false)
const cleanOver = ref(false)
/**
 * 查询输入框
 * @type {null}
 */
const searchInput = ref(null)

/**
 * 下拉框展示值
 * @type {Ref<UnwrapRef<string>>}
 */
const selectValue = ref("")

/**
 * 树数据
 * @type {Ref<UnwrapRef<*[]>>}
 */
const treeData = ref([])

/**
 * el-tree Ref
 * @type {null}
 */
const treeRef = ref(null)

/**
 * 鼠标控制输入框清除按钮
 */
const onMouseEvent = {
  verify: () => {
    if (attrs.clearable) {
      return true;
    }
    showClear.value = false
    return false
  },
  over: (e) => {
    if (onMouseEvent.verify()) {
      if (selectValue.value) {
        showClear.value = true
        return
      }
      showClear.value = false
    }
  },
  level: (e) => {
    if (onMouseEvent.verify()) {
      showClear.value = false
    }
  },
  cleanLevel: (e) => {
    if (onMouseEvent.verify()) {
      cleanOver.value = false
    }
  },
  cleanOver: (e) => {
    if (onMouseEvent.verify()) {
      cleanOver.value = true
    }
  }
}

/**
 * 优先级:options>dist>server
 */
const parserOptionsData = () => {
  /**
   * 判断传入值
   */
  if (props.options) {
    /**
     * 是Options
     */
    isOptionsType()
  } else if (props.dist) {
    /**
     *是字典类型
     */
    isDistType()
  } else if (props.server) {
    /**
     * 自定义服务类型
     */
    isServerType()
  }
}

/**
 * 赋值树结构数据
 * 作用：可以根据需要对树结构数据进行调整
 * @param data
 */
const generateDataOptions = (data) => {
  treeData.value = data
}

/**
 * 数据是Option处理
 */
const isOptionsType = () => {
  if (props.options && Array.isArray(props.options)) {
    generateDataOptions(props.options)
  }
}

/**
 * 数据是Dist
 * @returns {Promise<void>}
 */
const isDistType = async () => {
  let options = []
  if (props.dist) {
    let params = {}
    let dataLabel = 'data'
    if (typeof props.dist === 'string') {
      params = {name: props.dist}
    } else if (typeof props.dist === 'object') {

      if (props.dist.hasOwnProperty('name' && props.dist['name'])) {
        Object.assign(params, {name: props.dist['name']})
      }
      if (props.dist.hasOwnProperty('params') && props.dist['params']) {
        Object.assign(params, props.dist[params])
      }
      if (props.dist.hasOwnProperty('dataLabel') && props.dist['dataLabel']) {
        dataLabel = props.dist['dataLabel']
      }
    }
    let resp = await getDistData(params)
    options = resp[dataLabel]
  }
  generateDataOptions(options)
}
/**
 * 数据是自定义服务处理
 */
const isServerType = async () => {
  let option = await props.server()
  generateDataOptions(option)
}


/**
 * 搜索方法
 */
const search = async (val) => {
  await treeRef.value.filter(val)
}

/**
 * 根据设置获取label值
 * @param data
 * @returns {string|*}
 */
const getLabel = (data) => {
  if (localProps && localProps.label) {
    let labelObj = localProps.label
    if (typeof labelObj === 'string') {
      return data[labelObj]
    } else if (typeof labelObj === 'function') {
      return labelObj(data, null)
    }
  }
  return ""
}

/**
 * 节点过滤方法
 * @param value
 * @param data
 * @returns {boolean}
 */
const filterNode = (value, data) => {
  let label = getLabel(data)
  return label.includes(value)
}


const verifyParentNodeClick = (data) => {
  //父节点不允许点击
  if (data && props.parentNodeClick) {
    if (data[props.props.children] && data[props.props.children].length > 0) {
      ElMessage.warning("父节点不允许选中！")
      return true
    }
  }
  return false
}
const verifyNodeClickClose = () => {
  if (props.nodeClickClose) {
    visible.value = false
  }
}

/**
 * 处理节点点击事件并回传
 * @param data
 */
const handleNodeClick = (data) => {
  if (verifyParentNodeClick(data)) {
    return
  }
  verifyNodeClickClose()
  selectValue.value = getLabel(data)
  emits("nodeClick", data, getLabel(data))

}

/**
 * 清理状态的将节点清空
 */
const clearClick = () => {
  selectValue.value = null
  emits("nodeClick", null, "")
}

/**
 * 验证是否使用showCode属性
 */
const verifyShowCode = () => {
  if (props.showCode) {
    let tempLabel = props.props.label
    if (typeof props.props.label === 'string') {
      localProps.label = (data) => {
        if (data['code']) {
          return `${data['code']}  ${data[tempLabel]}`
        } else {
          return data[props.props.label]
        }
      }
    } else if (typeof props.props.label === 'function') {
      localProps.label = (data) => {
        if (data['code']) {
          return `${data['code']}  ${tempLabel(data)}`
        } else {
          return props.props.label(data)
        }
      }
    }
  }
}

onMounted(() => {
  verifyShowCode();
  nextTick(() => {
    parserOptionsData()
  })
})

const focusEvent = () => {
  visible.value = true
}

</script>

<style scoped lang="scss">
@import "../../styles/public/pub-bem";

@include b('select-tree') {
  &-content {
    height: 100% !important;
    overflow: auto;
    max-height: 200px;
  }
  &-option {
    &__input {
      position: absolute;
      z-index: 1000;
      margin: 0;
      padding: 0;
      width: 100%;
      height: 35px;
      top: 0;
      background-color: #ffffff
    }
  }
}
</style>
